#ifndef WORKSHE_H
#define WORKSHE_H

#include "boolean.h"
#include "mesinkata.h"
#include "custom_string.h"
#include <stdlib.h>
#include <stdio.h>

#define Nil NULL

typedef struct {
	int type;
	int bil;
	double real;
	string alfanum;
	boolean Bool;
	string Formula;
	} infotype;

typedef struct telmt *address;
typedef struct tHR *addressR;
typedef struct tHC *addressC;
typedef struct tOri *addressO;

typedef struct telmt {
	infotype Info;
	int AdrRow;
	string AdrCol;
	address NextR;
	address NextC;
	} Cell;
	
typedef struct tHC {
	string Info;
	address FirstCell;
	addressC NextCol;
	} HeaderColumn;
	
typedef struct tHR {
	int Info;
	address FirstCell;
	addressR NextBrs;
	} HeaderRow;
	
typedef struct tOri {
	addressC FirstCol;
	addressR FirstRow;
	} Origin;
	
typedef addressO Sheet;

//Selektor untuk Header Column
#define NextHC(HC) (HC)->NextCol
#define FirstCol(HC) (HC)->FirstCell
#define InfoCol(HC) (HC)->Info

//Selektor untuk Header Baris
#define NextHR(HR) (HR)->NextBrs
#define FirstBrs(HR) (HR)->FirstCell
#define InfoBrs(HR) (HR)->Info

//Selektor untuk Origin
#define NextColOri(S) (S)->FirstCol
#define NextBrsOri(S) (S)->FirstRow

//Selektor untuk Cell pada spreadsheet
#define NextCol(C) (C)->NextC
#define NextBrs(C) (C)->NextR
#define AdrBrs(C) (C)->AdrRow
#define AdrCol(C) (C)->AdrCol
#define Info(C) (C)->Info

//Selektor untuk infotype pada sel
#define InfoType(C) (C)->Info.type
#define InfoChar(C) (C)->Info.alfanum
#define InfoInt(C) (C)->Info.bil
#define InfoDouble(C) (C)->Info.real
#define InfoBoolean(C) (C)->Info.Bool
#define InfoFormula(C) (C)->Info.Formula

/* ***************** Manajemen Memori **************** */
addressO AlokasiOri ();
/* Mengalokasikan memori untuk Origin */

addressC AlokasiHC (string Info);
/* Mengalokasikan memori untuk satu elemen pada Header Column */

addressR AlokasiHR (int Info);
/* Mengalokasikan memori untuk satu elemen pada Header Baris */

address AlokasiCell (string Info);
/* Mengalokasikan memori untuk satu cell pada Spreadsheet */

void DealokasiO (addressO *P);
/* Mendealokasikan memori yang teralokasi untuk origin */

void DealokasiHR (addressR *P);
/* Mendealokasikan memori yang teralokasi untuk satu elemen pada Header Row */

void DealokasiHC (addressC *P);
/* Mendealokasikan memori yang teralokasi untuk satu elemen pada Header Column */

void DealokasiC (address *P);
/* Mendealokasikan memori yang teralokasi untuk satu Cell pada Spreadsheet*/

/* ***************** Membuat Spreadsheet Kosong dalam sistem **************** */
void CreateEmpty (Sheet *S);
/* Membuat sheet yang kosong yaitu terbentuk Origin dengan NextHeaderColomn dan NextHeaderRow bernilai Nil */

/* ***************** Predikat **************** */
boolean IsEmptySheet (Sheet S);
/* Mengecek apakah sheet kosong dengan parameter NextHeaderColomn dan NextHeaderRow bernilai Nil */

/* ***************** Insert/Delete/Get pada Spreadsheet **************** */
void InsertXY (Sheet *S, string Pos, string Isi);
/* Menambahkan satu cell pada Spreadsheet dengan elemen berupa Isi pada posisi (Column,Row) */

void GetXY (Sheet S, string Pos, address *Isi);
/* Mengambil alamat dari satu cell pada Spreadsheet dengan elemen berupa Isi pada posisi (Column,Row) */
/* Jika tidak ada cell dengan posisi (Column,Row) maka akan menghasilkan Nil */

void GetXYChar (Sheet S, string Pos, string *Isi);
/* Mengambil nilai pada sel dengan posisi (Column,Row) dalam tipe string */

void DeleteXY (Sheet *S, string Pos);
/* Menghapus satu cell pada Spreadsheet pada posisi (Column,Row) */

void DeleteAll (Sheet *S);
/* Menghapus semua sel yang ada dalam spreadsheet */

void RemoveArea (Sheet *S, string PosStart, string PosEnd);
/* Menghapus sel mulai dari PosStart hingga PosEnd dengan PosStart berada di kiri atas dan PosEnd berada di kanan bawah */

void MaxIndex (Sheet S, string *MaxIdx);

void PrintInfoType (address Isi);
/* Menampilkan info dari sel dengan berbagai kemungkinan yang ada */

#endif
